﻿
namespace StateTheater.Controllers
{        
	#region References

	using System;
	using System.Collections.Generic;
	using System.Drawing;
	using System.Linq;
	using System.Web;
	using System.Drawing.Imaging;
	using System.IO;
	using System.Net.Mail;
	using System.Configuration;
	using System.Web.Security;
	using System.Globalization;
	using System.Reflection;

	using Castle.MonoRail.Framework;
	using Castle.MonoRail.Framework.Helpers;
	using Castle.MonoRail.Framework.Filters;

	using StateTheater;
	using StateTheater.Models;
	using StateTheaterDataModel;
	using Castle.Components.Common.EmailSender;
	using System.Collections.Specialized;
	using System.Collections;
	using Castle.Components.Common.EmailSender.Smtp;
	using System.Data.Linq;
#endregion

//   [Filter(ExecuteWhen.BeforeAction, typeof(AuthenticationFilter))]
	[Layout("default", "Admin"), Rescue("generalerror")]
	public class AdminController : SmartDispatcherController
	{
		const string PhotoFormat = "person-{0}.jpg";

		StateTheaterDataContext db;
		public AdminController(StateTheaterDataContext db)
		{
			this.db = db;
		}

		private TextInfo textInfo = CultureInfo.CurrentCulture.TextInfo;
		public TextInfo TextInfo
		{
			get { return textInfo; }
			set { textInfo = value; }
		}


		#region Merge Dups
		public void MergeDups()
		{
		}
		[Rescue(typeof(JsonRescueController))]
		[return: JSONReturnBinder]
		public Status MergeDupsAjax(int bad, int good)
		{
			var badRecord = db.Peoples.FirstOrDefault(p => p.PersonID == bad);
			if (badRecord == null)
				return Status.BAD;

			db.Roles.Where(p => p.PersonID == bad).ToList().ForEach(r => r.PersonID = good);
			db.ProductionCredits.Where(p => p.PersonID == bad).ToList().ForEach(r => r.PersonID = good);
			db.PlayCredits.Where(p => p.PersonID == bad).ToList().ForEach(r => r.PersonID = good);
			db.ActorWatches.Where(p => p.PersonID == bad).ToList().ForEach(r => r.PersonID = good);
			db.TroupeMembers.Where(p => p.PersonID == bad).ToList().ForEach(r => r.PersonID = good);

			People pp = db.Peoples.Single(p => p.PersonID == good);

			pp.Bio = (from p in db.Peoples where new int[] { bad, good }.Contains(p.PersonID) select p.Bio).Max();
			pp.Photo = (from p in db.Peoples where new int[] { bad, good }.Contains(p.PersonID) select p.Photo).Max();
			db.Peoples.DeleteOnSubmit(badRecord);
			db.SubmitChanges();
			return Status.OK;
		}
		#endregion
		#region Bio Update
	public void BioUpdate()
	{

	}
	public void BioUpdate(int Id)
	{
		string user = this.Context.CurrentUser.Identity.Name;
		var current = db.Peoples.FirstOrDefault(p => p.PersonID == Id);
		bool isAdmin = this.Context.CurrentUser.IsInRole("Admin");

		if (isAdmin || (current != null && current.Member_Name.Equals(user, StringComparison.CurrentCultureIgnoreCase)))
		{
			PropertyBag["Allow"] = "User";

			int OldId = Id;
			BioCopy person = PersonController.GetPendingCopy(db, OldId);

			string imageRoot = HttpContext.Server.MapPath(@"~/content/images/");
			string filename = String.Format(PhotoFormat, OldId);
			string destFile = Path.Combine(Path.Combine(imageRoot, @"upload"), filename);

			if (!String.IsNullOrEmpty(person.Photo))
			{
				string srcFile = Path.Combine(Path.Combine(imageRoot, @"people"), person.Photo);
				if (File.Exists(srcFile) && !File.Exists(destFile))
				{
					File.Copy(srcFile, destFile, false);
				}
				person.Photo = filename;
			}
			PropertyBag["newBio"] = person;
		}
		else
			PropertyBag["Allow"] = "Reject";

	}

	public void UploadPhoto(HttpPostedFile uploadedPhoto, int PhotoId)
	{
		try
		{
			Bitmap photo = new Bitmap(uploadedPhoto.InputStream);
			photo = Util.ResizeImage(photo, 250, 300);

			string filename = String.Format(PhotoFormat, PhotoId);

			photo.Save(Path.Combine(HttpContext.Server.MapPath(@"~/content/images/upload"), filename), ImageFormat.Jpeg);
			PeoplePending pp = db.PeoplePendings.SingleOrDefault(p => p.PersonID == PhotoId);
			if (pp != null)
			{
				pp.Photo = filename;
				pp.ModUser = Context.CurrentUser.Identity.Name;
//				pp.ModTime = DateTime.Now;
				db.SubmitChanges();
			}
			RenderText("{{'status':'OK', 'filename':'{0}'}}", filename);
		}
		catch(Exception ex)
		{
			HttpContext.Response.StatusCode = 500;
			HttpContext.Response.StatusDescription = ex.Message;
			RenderText("{{'status':'BAD', 'Message':'{0}'}}", ex.Message);
		}

//		HttpContext.Response.ContentType = "application/x-json";
		CancelView();
	}

	[return: JSONReturnBinder]
	[Rescue(typeof(JsonRescueController))]
	public Status RemovePhoto(int id)
	{
		Status response = Status.OK;
		string filename = String.Format(PhotoFormat, id);
		try
		{
			File.Delete(Path.Combine(HttpContext.Server.MapPath(@"~/content/images/upload"), filename));
			PeoplePending pp = db.PeoplePendings.SingleOrDefault(p => p.PersonID == id);
			if (pp != null)
			{
				pp.Photo = null;
				pp.ModUser = Context.CurrentUser.Identity.Name;
				pp.ModTime = DateTime.Now;
				db.SubmitChanges();
			}
		}
		catch
		{
			response = Status.BAD;
		}
		return response;
	}

	[return: JSONReturnBinder]
	[Rescue(typeof(JsonRescueController))]
	public Status BioSave([DataBind("NewBio")] BioCopy info)
	{
		Status response = new Status("PENDING"); 
		try
		{
			PeoplePending pp = db.PeoplePendings.SingleOrDefault(p => p.PersonID == info.PersonID);
			pp.ActorsEquity = info.ActorsEquity;
			pp.Bio = info.Bio;
			pp.FirstName = info.FirstName;
			pp.LastName = info.LastName;
			pp.ModUser = Context.CurrentUser.Identity.Name;
			pp.ModTime = DateTime.Now;
			db.SubmitChanges(ConflictMode.ContinueOnConflict);

			if (Context.CurrentUser.IsInRole("Admin") || Context.CurrentUser.IsInRole("BioUpdate"))
			{
				Approve(info.PersonID);
				response = new Status("APPROVED");
			}

			var bio = db.Peoples.Where(p => p.PersonID == info.PersonID).First();
			PropertyBag.Add("Bio", bio);
			PropertyBag.Add("SEOName", Util.SEOEscape(bio.FullName, false));
			RecordUserAction(db, this, "bio", info.PersonID, PropertyBag);
		}
		catch (Exception ex)
		{
//				HttpContext.Response.StatusCode = 500;
			HttpContext.Response.StatusDescription = ex.Message;
			response = Status.BAD;
		}

		return response;
	}

	public void ApproveBioList()
	{
		var bb = (from p in db.PeoplePendings
					select new
					{
						Actor = p.FirstName + " " + p.LastName,
						Editor = p.ModUser,
						When = p.ModTime,
						ID = p.PersonID
					}).ToList();
		PropertyBag["Updates"] = bb;
	}

	public void BioApprove(int id)
	{
		BioUpdate(id);
	}

	public void ApproveBio(int id)
	{
		Approve(id);
		Response.Redirect("Admin", "ApproveBioList");
	}

	public void RejectBio(int id)
	{
		Reject(id);
		Response.Redirect("Admin", "ApproveBioList");
	}

	private void Reject(int id)
	{
		PeoplePending pp = db.PeoplePendings.SingleOrDefault(p => p.PersonID == id);
		if (pp != null)
		{
			if (!String.IsNullOrEmpty(pp.Photo))
			{
				string imageRoot = HttpContext.Server.MapPath(@"~/content/images/Upload");
				string srcPathname = Path.Combine(imageRoot, pp.Photo);
				File.Delete(srcPathname);
			}
			db.PeoplePendings.DeleteOnSubmit(pp);
			db.SubmitChanges();
		}
	}


	private void Approve(int id)
	{
#if true
		string newPhoto = null;
		string imageRoot = HttpContext.Server.MapPath(@"~/content/images/");
		PeoplePending pp = db.PeoplePendings.SingleOrDefault(p => p.PersonID == id);
		if (pp != null)
		{
			People person = db.Peoples.SingleOrDefault(p => p.PersonID == id);
			if (person != null)
			{
				if (!String.IsNullOrEmpty(pp.Photo))
				{
					string srcFilename = String.Format(PhotoFormat, id);

					string newFilename = Util.SEOEscape(person.FullName, false) + ".jpg";
					string newPathname = Path.Combine(Path.Combine(imageRoot, @"people"), newFilename);
					string srcPathname = Path.Combine(Path.Combine(imageRoot, @"upload"), pp.Photo);
					bool srcExists = File.Exists(srcPathname);
					bool destExists = File.Exists(newPathname);
					if (!srcExists)
					{
						if (!destExists)
							newPhoto = null;
					}
					else
					{
						newPhoto = newFilename;
						File.Copy(srcPathname, newPathname, true);
						File.Delete(srcPathname);
					}
				}
			}
			int updated = db.ApproveBio(id, newPhoto);
			if (updated == 1)
			{
				db.Refresh(RefreshMode.OverwriteCurrentValues, person);

				//db.PeoplePendings.DeleteOnSubmit(pp);
				//db.SubmitChanges();
			}
		}
#else
		PeoplePending pp = db.PeoplePendings.SingleOrDefault(p => p.PersonID == id);
		if (pp != null)
		{
			People person = db.Peoples.SingleOrDefault(p => p.PersonID == id);
			if (person != null)
			{
				person.ActorsEquity = pp.ActorsEquity;
				person.Bio = pp.Bio;
				person.FirstName = pp.FirstName;
				person.LastName = pp.LastName;
				person.ModTime = pp.ModTime.HasValue ? pp.ModTime.Value : DateTime.MinValue;
				person.ModUser = pp.ModUser;
				if (String.IsNullOrEmpty(pp.Photo))
				{
					person.Photo = null;
				}
				else
				{
					string imageRoot = HttpContext.Server.MapPath(@"~/content/images/");
					string srcFilename = String.Format(PhotoFormat, id);

					string newFilename = Util.SEOEscape(person.FullName, false) + ".jpg";
					string newPathname = Path.Combine(Path.Combine(imageRoot, @"people"), newFilename);
					string srcPathname = Path.Combine(Path.Combine(imageRoot, @"upload"), pp.Photo);
					bool srcExists = File.Exists(srcPathname);
					bool destExists = File.Exists(newPathname);
					if (!srcExists)
					{
						if (!destExists)
							person.Photo = null;
					}
					else
					{
						person.Photo = newFilename;
						File.Copy(srcPathname, newPathname, true);
						File.Delete(srcPathname);
					}
				}
				db.SubmitChanges();
			}
			db.PeoplePendings.DeleteOnSubmit(pp);
			db.SubmitChanges();
		}
#endif
	}


		#endregion
		#region Add Production



		public static void GetCounties(IDictionary bag, StateTheaterDataContext db)
		{
			bag["counties"] = (from c in db.Counties
									   orderby c.Name
									   select new SelectList(c.Name, c.CodeNum)).ToArray();
		}
		public void AddProduction(string name)
		{
			var troupe = db.Troupes.FirstOrDefault(t => t.shortname == name);
			if (troupe != null)
			{
				PropertyBag["TroupeExact"] = true;
				PropertyBag["TroupeId"] = troupe.TroupeID;
			}
			AddProduction();

		}

		public void AddProduction(int id)
		{
			var prod = db.Productions.FirstOrDefault(p => p.ProductionID == id);
			if (prod != null)
			{
				PropertyBag["ShowExact"] = true;
				PropertyBag["ProdId"] = id;
				PropertyBag["Prod"] = prod;

				PropertyBag["TroupeId"] = prod.TroupeID;

				//  return data.Title + ' | ' + data.Venue + ' (' + data.Year + ')';
				PropertyBag["ProdName"] = prod.Play.Title + " | " + prod.Venue.Name + " (" + prod.FirstPerformance.Year.ToString() + ")";
			}

			AddProduction();

		}


		public void AddProduction()
		{
			MembershipUser user = Membership.GetUser();
			if (user == null)
				return;
			int memberId = (int)user.ProviderUserKey;
			List<SelectList> troupes = null;
			if (Context.CurrentUser.IsInRole("Admin") | Context.CurrentUser.IsInRole("Super"))
			{
				troupes=
					(from t in db.Troupes
					 orderby t.Name
					 select new SelectList(t.Name, t.TroupeID)).ToList();
			}
			else if (Context.CurrentUser.IsInRole("Castlist"))
			{
				troupes =
					(from tp in db.TroupePermissions
					 where tp.MEMBER_ID == memberId
					 orderby tp.Troupe.Name
					 select new SelectList(tp.Troupe.Name, tp.Troupe.TroupeID)).ToList();
			}
			PropertyBag["troupes"] = troupes;
			PropertyBag["troupeIdSize"] = Math.Min(troupes.Count, 15);

			GetCounties(PropertyBag, db);
//			SELECT Name, CodeNum FROM Counties ORDER BY Name

//			TraceContext tc = new TraceContext(HttpContext);
//			tc.Render(new LinqLogWriter("trace", PropertyBag));

//			this.Logger.ErrorFormat("This is an error message to the logger");
		}


		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public SelectList[] SeasonsJson(int troupeid)
		{
			Response.CachePolicy.SetExpires(DateTime.Now.AddMinutes(2));
			
			var dates = (from pr in db.Productions
						where pr.TroupeID == troupeid
						group pr by 1 into grouping
						select new
						{
							first = grouping.Min(pr => pr.FirstPerformance),
							last = grouping.Max(pr => pr.FirstPerformance)
						}).FirstOrDefault();

			List<SelectList> seasonList = new List<SelectList>();
			if (dates != null)
			{

				var seasonStartMonth = (from t in db.Troupes
							  where t.TroupeID == troupeid
							  select t.SeasonStart).FirstOrDefault();

				seasonList = new List<SelectList>();
				if (seasonStartMonth == 1)
				{
					for (int year = dates.first.Year; year <= dates.last.Year; ++year)
					{
						seasonList.Add(new SelectList(string.Format("{0} season", year), string.Format("{0}-01-01", year)));
					}
				}
				else
				{
					int year = dates.first.Year;
					int endyear = dates.last.Year;
					if (dates.first.Month < seasonStartMonth)
						year--;

					if (dates.last.Month >= seasonStartMonth)
						endyear++;

					while (year < endyear)
					{
						seasonList.Add(new SelectList(string.Format("{0}-{1} season", year, year + 1), string.Format("{0}-{1}-01", year, seasonStartMonth)));
						++year;
					}
				}
				seasonList.Reverse();
			}
			return seasonList.ToArray();
		}

		public class ProductionList
		{
			public string ProductionId { get; set; }
			public string PlayId { get; set; }
			public string Title { get; set; }
			public string name { get; set; }
			public string VenueId { get; set; }
			public string FirstPerformance {get; set;}
			public string LastPerformance {get; set;}
			public DateTime FirstDate
			{
				set { FirstPerformance = value.ToShortDateString(); }
			}
			public DateTime? LastDate
			{
				set
				{
					LastPerformance = value == null ? FirstPerformance : value.Value.ToShortDateString();
				}
			}
		}

		[return:JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public jqGridPacket<ProductionList> ProductionsJson(int TroupeID, string Season)
		{
			DateTime seasonStart = DateTime.ParseExact(Season, "yyyy-M-d", CultureInfo.CurrentCulture);
			var productions = from pr in db.Productions
							  where pr.TroupeID == TroupeID
							  && pr.FirstPerformance >= seasonStart
							  && pr.FirstPerformance < seasonStart.AddYears(1)
							  select new ProductionList
							  {
									  ProductionId = pr.ProductionID.ToString(),
									  PlayId = pr.PlayID.ToString(),
									  Title = pr.Play.Title,
									  name = pr.Venue.Name,
									  VenueId = pr.VenueID.Value.ToString(),
									  FirstDate = pr.FirstPerformance,
									  LastDate = pr.LastPerformance 
							  };

			jqGridPacket<ProductionList> packet = new jqGridPacket<ProductionList>(productions);
			return packet;
		}
		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public SelectList[] SchedulesJson(int troupeid)
		{
			var q = from ss in db.StandardSchedules
					where ss.TroupeID == troupeid || ss.TroupeID == null
					select new SelectList(ss.Name, ss.SchedID);

			return q.ToArray();
		}


		#endregion
		#region FAQ Editor
		public void FaqEditor()
		{
			var faqs = db.FAQs.OrderBy(f=>f.Seq).ToList();
			PropertyBag["faqs"] = faqs;
		}

		public void FaqEditor(int id, int Seq, string txtQuestion, string txtAnswer)
		{
			FAQ faq = db.FAQs.Where(f => f.FaqID == id).FirstOrDefault();
			if (faq == null)
			{
				faq = new FAQ();
				db.FAQs.InsertOnSubmit(faq);
			}

			faq.Seq = Seq;
			faq.Question = txtQuestion;
			faq.Answer = txtAnswer;
			db.SubmitChanges();
			FaqEditor();
		}

		public void SaveFAQText(int id, string txt, int which)
		{
			bool success = true;
			string response = "success";
			CancelView();

			using (db.Transaction)
			{
				FAQ faq = db.FAQs.Where(f => f.FaqID == id).FirstOrDefault();
				if (faq == null)
				{
					faq = new FAQ();
					faq.Answer = "filler";
					faq.Question = "filler";
					faq.Seq = 5;
					db.FAQs.InsertOnSubmit(faq);
					response = "insert";
				}

				switch (which)
				{
					case 1:
						if (faq.Question == txt)
						{
							response = "nochange";
							success = false;
						}
						else
							faq.Question = txt;
						break;

					case 2:
						if (faq.Answer == txt)
						{
							response = "nochange";
							success = false;
						}
						else
							faq.Answer = txt;
						break;

					default:
						response = "error";
						success = false;
						return;
				}
				if (success)
				{
					try
					{
						db.SubmitChanges();
						db.Transaction.Commit();
					}
					catch (Exception ex)
					{
						db.Transaction.Rollback();
						while (ex != null)
						{
							response = ex.Message;
							ex = ex.InnerException;
						}
					}
				}
			}
			this.HttpContext.Response.ContentType = "application/x-json";
			RenderText(response);
		}

		public class xFAQ
		{
			public int FaqID { get; set; }
			public string Question { get; set; }
			public string Answer { get; set; }
			public int Seq { get; set; }
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public jqGridPacket<xFAQ> FaqListJson()
		{
			//var faqs = db.FAQs.OrderBy(f => f.Seq);
			var faqs = from faq in db.FAQs
					   orderby faq.Seq
					   select new xFAQ
					   {
						   FaqID = faq.FaqID,
						   Question = faq.Question,
						   Answer = faq.Answer,
						   Seq = faq.Seq,
					   };

			string strStart = Params["start"] as string;
			string strLimit = Params["limit"] as string;
			int start;
			int limit;

			if (Int32.TryParse(strStart, out start))
				faqs = faqs.Skip(start) as IOrderedQueryable<xFAQ>;
			if (Int32.TryParse(strLimit, out limit))
				faqs = faqs.Take(limit) as IOrderedQueryable<xFAQ>;

			return new jqGridPacket<xFAQ>(faqs);
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public int MoveFaq(int faqid, int newPos)
		{
			return db.MoveFAQ(faqid, newPos);
		}
		#endregion
		#region Cast List Editor
		class CreditLine
		{
			public int ID { get; set; }
			public string Credit { set; get; }
		}

		public void CastList()
		{
			PropertyBag["CrewCredits"] =
			(from cr in db.CreditNames
			 orderby cr.Credit
			 where cr.CreditID > 99
			 select new CreditLine
			 {
				 Credit = cr.Credit + " by",
				 ID = cr.CreditID
			 }).ToArray();

			PropertyBag["AuthorCredits"] =
			(from cr in db.CreditNames
			 orderby cr.Credit
			 where cr.CreditID < 100
			 select new CreditLine
			 {
				 Credit = cr.Credit + " by",
				 ID = cr.CreditID
			 }).ToArray();

			// SELECT [CreditID], [Credit] + ' by ' as [Credit] FROM [CreditNames] WHERE ([CreditID] " + limit + ") order by 2";
		}

		public void CastList(int id)
		{
			var prod = db.Productions.FirstOrDefault(p => p.ProductionID == id);
			if (prod != null)
			{
				PropertyBag["ShowExact"] = true;
				PropertyBag["ProdId"] = id;
				//  return data.Title + ' | ' + data.Venue + ' (' + data.Year + ')';
				PropertyBag["ProdName"] = prod.Play.Title + " | " + prod.Venue.Name + " (" + prod.FirstPerformance.Year.ToString() + ")";
			}

			CastList();

		}
		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public Status AddCastMember(int prodid, int person, string roleName)
		{
			Role role = new Role();
			role.PersonID = person;
			role.ProductionID = prodid;
			role.Role1 = TextInfo.ToTitleCase(roleName);

			db.Roles.InsertOnSubmit(role);
			db.Productions.First(pr => pr.ProductionID == prodid).HasCast = true;
			db.SubmitChanges();
			return Status.OK;
		}


		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public string DeleteCast(int id, string oper, int which)
		{
			if (Context.CurrentUser.IsInRole("castlist") || Context.CurrentUser.IsInRole("admin"))
			{
				if (oper == "del")
				{
					switch (which)
					{
						case 0:
							Role role = db.Roles.FirstOrDefault(r => r.RoleID == id);
							if (role != null)
							{
								db.Roles.DeleteOnSubmit(role);
							}
							break;
						case 1:
							ProductionCredit pc = db.ProductionCredits.FirstOrDefault(p => p.PK == id);
							if (pc != null)
							{
								db.ProductionCredits.DeleteOnSubmit(pc);
							}
							break;
						case 2:
							PlayCredit plc = db.PlayCredits.FirstOrDefault(p=>p.PK == id);
							if (plc != null)
							{
								db.PlayCredits.DeleteOnSubmit(plc);
							}
							break;
					}
					db.SubmitChanges();
					return "OK";
				}
			}
			return "error";
		}


#endregion
		#region Edit Announcements
		public void EditAnnouncements()
		{
		}

		public class AnnouncementPacket
		{
			public AnnouncementPacket(Announcement ann)
			{
				this.ann = ann;
			}
			private Announcement ann;
			public string PK { get { return ann.PK.ToString(); } }
			public string Priority { get { return ann.Priority.ToString(); } }
			public string StartDate { get { return ann.StartDate.HasValue ? ann.StartDate.Value.ToShortDateString() : "(no start date)"; } }
			public string EndDate { get { return ann.EndDate.HasValue ? ann.EndDate.Value.ToShortDateString() : "(no end date)"; } }
			public string Text { get { return ann.Text; } }
		}

		[return:JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public jqGridPacket<AnnouncementPacket> AnnouncementsJson()
		{
			return new jqGridPacket<AnnouncementPacket>(db.Announcements.Select(a=>new AnnouncementPacket(a)).ToArray());
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public string SaveAnnouncement(int AnnouncementID, string txtComments, int Priority)
		{
			return SaveAnnouncement(AnnouncementID, txtComments, null, null, Priority);
		}
		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public string SaveAnnouncement(int AnnouncementID, string txtComments, DateTime? StartDate, DateTime? EndDate, int Priority)
		{
			CancelLayout();
			Announcement ann=null;
			if (AnnouncementID != 0)
				ann = db.Announcements.FirstOrDefault(a => a.PK == AnnouncementID);

			if (ann == null)
			{
				ann = new Announcement();
				db.Announcements.InsertOnSubmit(ann);
			}

			ann.Priority = Priority;
			ann.StartDate = StartDate;
			ann.EndDate = EndDate;
			ann.Text = txtComments;
			db.SubmitChanges();
			return "OK";
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public string SaveAnnouncement(int id, string oper)
		{
			if (Context.CurrentUser.IsInRole("Admin"))
			{
				if (oper == "del")
				{
					Announcement ann= db.Announcements.FirstOrDefault(a=> a.PK == id);
					if (ann!= null)
					{
						db.Announcements.DeleteOnSubmit(ann);
						db.SubmitChanges();
						return "OK";
					}
				}
			}
			return "error";
		}

		#endregion
		#region Edit Play
		public void EditPlay()
		{
		}
		#endregion
		#region Edit Show Photos
		public void EditPhotos()
		{
		}
		public void EditPhotos(int id)
		{
			var prod = db.Productions.FirstOrDefault(p => p.ProductionID == id);
			if (prod != null)
			{
				PropertyBag["ShowExact"] = true;
				PropertyBag["ProdId"] = id;
				PropertyBag["ProdName"] = prod.Play.Title + " | " + prod.Venue.Name + " (" + prod.FirstPerformance.Year.ToString() + ")";
//			PropertyBag["details"] = ProductionDetails.GetDetails(db, id);

			PropertyBag["photos"] = (
				from ph in db.Photos
				where ph.productionID == id
				select new
				{
					id = ph.PK,
					ph.Filename,
					ph.Caption
				}).ToList();
			}

			EditPhotos();
		}

		public void GetPhotoCaption(int id)
		{
			CancelView();
			RenderText(db.Photos.Where(ph => ph.PK == id).First().Caption);
		}
		#endregion
		#region Utility
		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public Status RecordCastList(int id)
		{
			var q = (from pr in db.Productions
					 where pr.ProductionID == id
					 select new
					 {
						 Title = pr.Play.Title,
						 Venue = pr.Venue.Name,
						 Year = pr.FirstPerformance.Year
					 }).FirstOrDefault();

			PropertyBag.Add("Title", q.Title);
			PropertyBag.Add("Venue", q.Venue);
			PropertyBag.Add("Year", q.Year);
			PropertyBag.Add("Id", id);

			RecordUserAction(db, this, "castlist", id, PropertyBag);
			return Status.OK;
		}

		public void RecordUserActionJson(string action, int id)
		{
			RecordUserAction(db, this, action, id, PropertyBag);
			CancelView();
			CancelLayout();
		}

		public static void MailMessage(FORUM_MEMBER user, Controller ctrl, string action, IDictionary parms)
		{
			parms["webRoot"] = ctrl.Context.ApplicationPath;
			parms["Uri"] = ctrl.Request.Uri;

			parms["User"] = user;
			parms["FromEmail"] = user.M_EMAIL ?? ConfigurationManager.AppSettings["SysadminEmail"];
			parms["alertEmail"] = ConfigurationManager.AppSettings["alertEmail"];
			parms["SysadminEmail"] = ConfigurationManager.AppSettings["SysadminEmail"];

			try
			{
				MailMessage email = ctrl.RenderMailMessage(action, null, parms);
				email.IsBodyHtml = true;
				ctrl.DeliverEmail(email);
			}
			catch (Exception ex)
			{
				System.Diagnostics.Trace.TraceError("UserActions Error: {0}", ex.Message);
			}
		}
		public static FORUM_MEMBER GetUser(StateTheaterDataContext db)
		{
			int memberId = (int)Membership.GetUser().ProviderUserKey;
			var user = db.FORUM_MEMBERs.FirstOrDefault(me => me.MEMBER_ID == memberId);
			return user;
		}
		public static void RecordUserAction(StateTheaterDataContext db, Controller ctrl, string action, int id, IDictionary parms)
		{
			FORUM_MEMBER user = GetUser(db);
			parms["ID"] = id;

			MailMessage(user, ctrl, action, parms);
			try
			{
				UserAction UAction = new UserAction();
				UAction.Action = action;
				UAction.ObjectID = id;

				UAction.ActionTime = DateTime.Now;
				UAction.UserName = ctrl.Context.CurrentUser.Identity.Name;  // "James"; //  

				db.UserActions.InsertOnSubmit(UAction);
				db.SubmitChanges();
			}
			catch (Exception ex)
			{
				System.Diagnostics.Trace.TraceError("UserActions Error: {0}", ex.Message);
			}
		}
		#endregion
	}
}

